/*
 *	Chemical equation balancer
 *
 *	Copyright (C) 2011 XiaoJSoft Studio. All Rights Reserved.
 *	Copyright (C) Ji WenCong <whs_jwc@163.com>
 *
 *	This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include "../include/equation.h"
#include "../include/interpreter.h"
#include "../include/format.h"
#include "../include/kernel.h"

/*
 *	char* balanceCE(char *equ, int full);
 *
 *	To balance the chemical equation and returns the results.
 *
 *	*equ		->	the chemical equation,
 *	full		->	a bool value, if you need to want to see the full balanced chemical equation.
 */
char* balanceCE(char *equ, int full)
{
	char *fmt1, *fmt2;
	int idx;
	estack *build;
	fact *equSolved;
	long double *blc;
	int *blcInt;

	/*  Converting the chemical equation into mathematic equations  */
	build = getElementStack(equ);
	if (build == NULL) {
		return(NULL);
	}

	/*  Solving the mathematic equations  */
	equSolved = solveEquations(build->equations, build->constants, build->maxX, build->maxY);
	if (equSolved == NULL) {
		free(build->equations);
		free(build->constants);
		free(build);
		return(NULL);
	}

	/*  Converting the fractions into real number  */
	blc = fractionToNumber(equSolved, build->maxX);
	if (blc == NULL) {
		free(equSolved);
		free(build->equations);
		free(build->constants);
		free(build);
		return(NULL);
	}

	/*  Converting the long double heap into integer heap  */
	blcInt = lfToInt(blc, build->maxX);
	for (idx = 1; idx <= build->maxX; idx++) {
		if (*(blcInt + idx - 1) < 0) {
			free(blc);
			free(equSolved);
			free(build->equations);
			free(build->constants);
			free(build);
			return(NULL);
		}
	}

	if (blcInt == NULL) {
		free(blc);
		free(equSolved);
		free(build->equations);
		free(build->constants);
		free(build);
		return(NULL);
	}

	if (full == 1) {
		/*  Formatting it and returning it  */
		fmt1 = formatResult(equ, blcInt, build->maxX);

		free(equSolved);
		free(blc);
		free(blcInt);
		free(build->equations);
		free(build->constants);
		free(build);

		if (fmt1 == NULL) {
			return(NULL);
		}

		fmt2 = formatResult2(fmt1);

		return(fmt2);
	} else {
		/*  Generating a new string  */
		fmt1 = (char*) malloc(1 * sizeof(char));
		if (fmt1 == NULL) {
			free(equSolved);
			free(blc);
			free(blcInt);
			free(build->equations);
			free(build->constants);
			free(build);
			return(NULL);
		}
		*fmt1 = '\0';

		/*  Formatting it  */
		for (idx = 1; idx <= build->maxX; idx++){
			if (idx == build->maxX) {
				kasprintf(&fmt2, "%s%d", fmt1, *(blcInt + idx - 1));
			} else {
				kasprintf(&fmt2, "%s%d, ", fmt1, *(blcInt + idx - 1));
			}
			free(fmt1);
			fmt1 = fmt2;
			fmt2 = NULL;
			if (fmt1 == NULL) {
				free(equSolved);
				free(blc);
				free(blcInt);
				free(build->equations);
				free(build->constants);
				free(build);
				return(NULL);
			}
		}

		free(equSolved);
		free(blc);
		free(blcInt);
		free(build->equations);
		free(build->constants);
		free(build);

		return(fmt1);
	}
}

